// import React from 'react'
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { TableProps } from 'antd/lib/table';
import useApiLoading, { UseApiLoadingReturnValueType } from './useApiLoading';
import useStateStack from './useStateStack';

export interface PaginationEntity<T> {
  pageIndex: number;
  pageSize: number;
  data: Array<T>;
  total: number;
}

export interface UsePaginationReturnValueType<T>
  extends PaginationEntity<T>,
    Omit<UseApiLoadingReturnValueType, 'api'> {
  props: Partial<TableProps<T>>;
}

export interface ApiFunctionType<T> {
  (paginationEntity: PaginationEntity<T>): Promise<PaginationEntity<T>>;
}

export interface UsePaginationType {
  <T>(api: ApiFunctionType<T>): UsePaginationReturnValueType<T>;
  initialPageSize: number;
}

const usePagination: UsePaginationType = function usePagination<
  T
>(api: ApiFunctionType<T>): UsePaginationReturnValueType<T> {
  /**
   * state
   */
  const loadingContext = useApiLoading(api);
  const { apiLoading, apiState } = loadingContext;
  const wrappedApi = loadingContext.api as ApiFunctionType<T>;
  const [data, setData] = useState<Array<T>>([]);
  const [pageIndex, setPageIndex] = useState<number>(1);
  const [pageSize, setPageSize] = useState<number>(
    usePagination.initialPageSize
  );
  const [total, setTotal] = useState<number>(0);

  /**
   * record state
   */
  const dataId = `${pageIndex} - ${pageSize}`;
  const currentState = { pageIndex, pageSize, total, data, id: dataId };
  const { top, push } = useStateStack(currentState, {
    autoPush: false,
  });

  /**
   * requery method
   */
  const requery = useRef(() => {});
  requery.current = () => {
    return wrappedApi({
      data,
      pageIndex,
      pageSize,
      total,
    })
      .then(function ({ data, pageIndex, pageSize, total }) {
        setData(data);
        setPageIndex(pageIndex);
        setPageSize(pageSize);
        setTotal(total);
        const currentState = { data, pageIndex, pageSize, total, id: dataId };
        if (top() == null) {
          push({
            ...currentState,
            id: '',
          });
        }
        push(currentState);
      })
      .catch((e) => {
        const prevState = top();
        if (prevState != null) {
          setData(prevState.data);
          setPageIndex(prevState.pageIndex);
          setPageSize(prevState.pageSize);
          setTotal(prevState.total);
        }
        console.log('usePagination api failed', prevState, currentState);
      });
  };
  /**
   * preset table
   */
  const handlePaginationChange = useCallback(
    (current: number, size?: number) => {
      setPageSize(size || usePagination.initialPageSize);
      setPageIndex(current);
    },
    []
  );
  const presetPaginationOptions = useMemo(
    () => ({
      current: pageIndex,
      pageSize: pageSize,
      total: total,
      onShowSizeChange: handlePaginationChange,
      onChange: handlePaginationChange,
      hideOnSinglePage: true,
      showQuickJumper: true,
    }),
    [handlePaginationChange, pageIndex, pageSize, total]
  );
  const presetTableOptions = useMemo(
    () => ({
      loading: apiLoading,
      dataSource: data,
      pagination: presetPaginationOptions,
    }),
    [apiLoading, data, presetPaginationOptions]
  );
  /**
   * data to export
   */
  useEffect(() => {
    requery.current();
  }, [pageIndex, pageSize, requery]);

  return {
    data,
    pageIndex,
    pageSize,
    total,
    apiLoading,
    apiState,
    props: presetTableOptions,
  };
};

usePagination.initialPageSize = 10;

export default usePagination;
